`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: James Forrest
// 
// Create Date:    21:59:21 09/10/2013 
// Design Name: 
// Module Name:    HexKeypadController 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module HexKeypadController(input             clk,
                           input             reset,
                           input             enable,
                           input       [3:0] address,
                           input      [31:0] dataIn,
                           output reg [31:0] dataOut,
                           input             write,
                           output            done,
                           output            interrupt,
                           input             clk_50,
                           inout       [7:0] keypad
                           );

    // nothing in this controller requires more than one cycle to complete
    assign done = 1'b1;

    // register to hold the data 8x4-bits (8th to last button, 7th to last button, ..., 2nd to last button, last button)
    reg [31:0] pressedBuffer;
    wire [3:0] pressedData;
    wire       pressedFlag, normPressedFlag;
    reg        prevPressedFlag;

    // use a counter to check if read since read
    reg [31:0] count;
    reg [31:0] compare;
    reg [31:0] interruptStep;

    // the controllers don't get reset, so necessary to use initial
    initial begin
        pressedBuffer = 0;
        count = 0;
        compare = 0;
        interruptStep = 0;
    end

    // if pressed at least interrupt step more than last read, raise interrupt
    assign interrupt = (count > (compare + interruptStep+1));

    always @ (posedge clk, posedge reset) begin
        // reset if on
        if (reset) begin
            pressedBuffer <= 32'd0;
            count <= 32'd0;
            compare <= 32'd0;
            interruptStep <= 32'd0;
        end
        else begin // run
            // if memory bus
            if (enable)
                // write to this controller
                if (write)
                    case (address)
                        4'h3: interruptStep <= dataIn-1;   // write the interrupt step
                        default: ;                         // no other write addresses
                    endcase
                else
                    // read from address
                    case (address)
                        4'h0: begin
                                 dataOut <= pressedBuffer; // buffer of last eight buttons pressed
                                 compare <= count;         // update last read
                              end
                        4'h1:    dataOut <= count;         // count of buttons pressed
                        4'h2:    dataOut <= compare;       // index of last button read
                        4'h3:    dataOut <= interruptStep+1;//number of key presses before interrupt is raised
                        4'hF:    dataOut <= {4'hA, 2'b10, 2'b11, 3'd0, 3'd0, 6'd0, 8'd0, 4'hA}; // Dynamic Recognition Protocol
                        default: dataOut <= 4'h0;          // nothing else implemented
                    endcase
            if (normPressedFlag) begin
                // increment counter
                count <= count + 32'd1;
                // push onto buffer
                pressedBuffer <= {pressedBuffer[27:0], pressedData};
            end
            // save flag at clock
            prevPressedFlag <= pressedFlag;
        end
    end

    // use decoder to get current state
    HexKeypadDecoder decoder(clk_50, keypad, pressedFlag, pressedData);

    // normalise the flag to one cycle
    assign normPressedFlag = (prevPressedFlag ^ pressedFlag) & pressedFlag;

endmodule
